<?php

namespace tests;

use app\mall\model\User;
use app\Request;
use catcher\base\CatchRequest;
use catcher\CatchAuth;
use catcher\CatchResponse;
use catcher\Code;
use http\Cookie;
use \PHPUnit\Framework\TestCase;
use app\common\model\AdminToken;
use app\common\model\AdminUser;
use thans\jwt\JWT;
use thans\jwt\JWTAuth;
use think\response\Json;

/**
 * 控制器中的Request对象，
 * Class TestRequest
 * @author lxg
 * @package tests
 */
class TestRequest extends Request
{
    public $data = [];
    public $isPost;
    public $isGet = true;
    public $isAjax = true;

    function setParam($data)
    {
        $this->param = $data;
    }
}


class ParamRemark
{
    public $field;
    public $value;
    public $required;
    public $remark;

    public function __construct($field, $value, $required, $remark)
    {
        $this->field = $field;
        $this->value = $value;
        $this->required = $required;
        $this->remark = $remark;
    }
}


/**
 * 控制器测试助手
 * Trait ControllerTestHelper
 * @author lxg
 * @package tests
 *
 * 商户 160 cc2222222 adminId: 1005
 */
trait TestHelper
{
    /**
     * @var TestRequest
     */
    protected $request;

    public $required = [];
    /**
     * @var ParamRemark
     */
    public $paramRemark = [];


    function getRequest(): Request
    {
        return $this->request;
    }


    public function methodDelete(): self
    {
        $this->request->setMethod('DELETE');
        $_SERVER['REQUEST_METHOD'] = 'DELETE';
        return $this;
    }

    public function methodPut(): self
    {
        $this->request->setMethod('PUT');
        $_SERVER['REQUEST_METHOD'] = 'PUT';
        return $this;
    }

    public function setRequired(...$s)
    {
        $this->required = $s;
        return $this;
    }

    public static function getInterface(...$args)
    {

        $self = new self(...$args);

        $userParam = [
            "email" => "admin@admin.com",
            "password" => "admin@2021"
        ];
        $auth = new CatchAuth();
        $auth->attempt($userParam);
        $request = new TestRequest();
        $self->request = $request;

        return $self;
    }

    public static function NewToken(array $userParam, ...$args)
    {

        $self = new self(...$args);

        $auth = new CatchAuth();
        $auth->attempt($userParam);

        $request = new TestRequest();
        $self->request = $request;

        return $self;
    }

    public static function getAdminInterface(...$args)
    {

        $self = new self(...$args);


        $userParam = [
            "username" => "test2",
            "password" => "test2"
        ];
        $auth = new CatchAuth();
        $auth->guard('platform')->attempt($userParam);
        $request = new TestAdminRequest();
        $self->request = $request;

        return $self;
    }

    /**
     * @param array paramRemark
     * @author: lxg
     */
    public function setPost(ParamRemark ...$data)
    {

        $this->setParam(...$data);
        $this->request->isPost = true;
        $this->request->setMethod('POST');
        $_SERVER['REQUEST_METHOD'] = 'POST';
        return $this;
    }

    /**
     * @param $data
     * @author: lxg
     */
    public function setParam(ParamRemark ...$data): self
    {

        $this->paramRemark = $data;
        $newData = [];
        foreach ($data as $field => $value) {
            if ($value instanceof ParamRemark) {
                $newData[$value->field] = $value->value;
            } else {
                $newData[$field] = $value;
            }
        }

        $this->request->data = $newData;
        $this->request->setParam($newData);
        if ($this->request->isPost == false) {
            $_GET = $newData;
        }
        return $this;
    }

    public function setParamRemark($data)
    {
        $this->paramRemark = $data;
        return $this;
    }

    public function addParamRemark($find, $value = '', $required = false, $remark = '')
    {
        return new ParamRemark($find, $value, $required, $remark);
    }

    function success($data = [], $msg = 'success', $code = Code::SUCCESS): Json
    {
        echo("##### 返回成功:\n");
        $codeContent = json_encode(['code' => $code, 'data' => $data, 'msg' => $msg], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        echo "``` \n{$codeContent}\n```";
        return CatchResponse::success($data, $msg, $code);
    }

    function fail($msg = '', $code = Code::FAILED): Json
    {
        printf("##### 返回失败\n", $code);
        $codeContent = json_encode(['code' => $code, 'error_msg' => $msg], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        echo "``` \n{$codeContent}\n```";
        return CatchResponse::fail($msg, $code);
    }

    //打印Markdown参数，供写API文档使用
    public function printMarkdown($apiName = '', $apiUrl = '', $paramRemark = [])
    {
        if (!empty($paramRemark)) {
            $this->setParam($paramRemark);
        }
        printf("\n## {$apiName} \n");
        $method = $this->request->method();
        if (empty($method)) {
            $method = 'GET';
        }
        $method = sprintf("[%s]", $method);

        printf("\n#####  {$method} {$apiUrl} \n");
        printf("\n##### 请求参数 \n");
        printf("|参数|是否必填|说明|\n");
        printf("|---|---|---|\n");
        foreach ($this->paramRemark as $key => $param) {
            if ($param instanceof ParamRemark) {
                if (is_array($param->value)) {
                    $val = json_encode($param->value, JSON_UNESCAPED_UNICODE);
                } else {
                    $val = $param->value;
                }
                $requiredText = $param->required ? '是' : '否';
                $val = $val . ';' . $param->remark;
                $key = $param->field;
            } else {
                if (is_array($param)) {
                    $val = json_encode($param, JSON_UNESCAPED_UNICODE);
                } else {
                    $val = $param;
                }

                $requiredText = '否';
                if (in_array($key, $this->required) || (isset($this->required[0]) && $this->required[0] == 'all')) {
                    $requiredText = '是';
                }
            }

            printf("|%s|%s|%s=%s|\n", $key, $requiredText, $key, $val);
        }
        return $this;
    }
}

class TestBase extends TestCase
{

    static function newParam($find, $value = '', $required = false, $remark = ''): ParamRemark
    {
        return new ParamRemark($find, $value, $required, $remark);
    }
}

class Test
{
    use TestHelper;

    function output($data)
    {
        $codeContent = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        echo "``` \n{$codeContent}\n```";
    }
}
